home *** CD-ROM | disk | FTP | other *** search
/ CYBER.XPO.95 / CYBER.XPO.95 (Arsenal Computer).ISO / popreq / amiga1 / a1000hks.lha / TicTac / TicTac.c < prev    next >
C/C++ Source or Header  |  1993-03-12  |  14KB  |  531 lines

  1. /*************************************************************************/
  2. /* TicTac.c     Betriebsprogramm zum Lesen und Stellen einer             */
  3. /*              Hardwareuhr am Joystickport#2 am A1000                   */
  4. /*              c't 1987, Heft 8                                         */
  5. /*                                                                       */
  6. /*              Funktion:                                                */
  7. /*                TicTac         Zeit und Datum des Uhrenchips anzeigen  */
  8. /*                TicTac load    Chip lesen und Systemzeit stellen       */
  9. /*                TicTac save    Systemzeit lesen und Chip stellen       */
  10. /*                                                                       */
  11. /*              Optimierte Version von A. Peter, 10.01.1992              */
  12. /*************************************************************************/
  13.  
  14.  
  15. #include <exec/types.h>
  16. #include <exec/nodes.h>
  17. #include <exec/memory.h>
  18. #include <exec/interrupts.h>
  19. #include <exec/libraries.h>
  20. #include <exec/tasks.h>
  21. #include <exec/io.h>
  22. #include <exec/devices.h>
  23. #include <devices/timer.h>
  24. #include <libraries/dos.h>
  25.  
  26.  
  27. #define DATRX 0x1000
  28. #define OUTRX 0x2000
  29. #define DATRY 0x4000
  30. #define OUTRY 0x8000
  31.  
  32. #define OnlyBit7   '\200'
  33. #define AllButBit7 '\177'
  34.  
  35. #define SELECT          WritePotgo(0x2000,SelectMask)
  36. #define DESELECT        WritePotgo(0x3000,SelectMask)
  37. #define CLOCKHIGH       WritePotgo(0x8000,ClockMask)
  38. #define CLOCKLOW        WritePotgo(0xC000,ClockMask)
  39. #define SETDATATOINPUT  *myddrao &= AllButBit7
  40.  
  41. struct TimeAndDate {
  42.    int TDhours;
  43.    int TDminutes;
  44.    int TDseconds;
  45.    int TDday_of_week;
  46.    int TDdate;
  47.    int TDmonth;
  48.    int TDyear;
  49.    };
  50.  
  51. struct DosLibrary *DOSBase;
  52.  
  53. APTR *PotgoBase;
  54. char *myddrao;
  55. char *myprao;
  56.  
  57. extern struct MsgPort *CreatePort();
  58. extern struct IORequest *CreateExtIO();
  59.  
  60. struct TimeAndDate ToBeRead,ToBeWritten;
  61.  
  62. UWORD allocated,bits;
  63. char  firedata;
  64.  
  65. SelectMask = DATRX | OUTRX;
  66. ClockMask  = DATRY | OUTRY;
  67.  
  68. LONG monthseconds[] = {
  69.    0L,0L,      2678400L,  5097600L,  7776000L,
  70.    10368000L, 13046400L, 15638400L, 18316800L,
  71.    20995200L, 23487200L, 26265600L, 28857600L };
  72.  
  73. void                               /* Routinen zum Datenleitung (FIRE) */
  74. DataHigh()                         /* auf HIGH oder LOW legen          */
  75.    {
  76.       *myddrao |= OnlyBit7;
  77.       *myprao  |= OnlyBit7;
  78.    }
  79.  
  80. void
  81. DataLow()
  82.    {
  83.       *myddrao |= OnlyBit7;
  84.       *myprao  &= AllButBit7;
  85.    }
  86.  
  87. char                         
  88. IntToBCD(value)                    /* Umwandlung des Integer-Formats */
  89.    int value;                      /* in fⁿr den Chip verstΣndliches */
  90.    {                               /* BCD-Format */
  91.  
  92.       return((((value % 100 - value %10)/10)<<4)+ value % 10);
  93.    }
  94.  
  95. int                                /* Gegenteil von IntToBCD()       */
  96. BCDToInt(decimal)
  97.    char decimal;
  98.    {
  99.       return (((decimal >>4)& '\017')*10 + (decimal & '\017'));
  100.    }
  101.  
  102. void                               /* L÷schen des eigenen TimerPorts */
  103. DeleteTimer(tr)
  104.    struct timerequest *tr;
  105.    {
  106.       struct MsgPort *tp;
  107.  
  108.          tp = tr->tr_node.io_Message.mn_ReplyPort;
  109.          if(tp != NULL)
  110.             DeletePort(tp);
  111.          CloseDevice(tr);
  112.          DeleteExtIO(tr,sizeof(struct timerequest));
  113.  
  114.    }
  115.  
  116.  
  117. struct timerequest *               /* Eigenen TimerPort erstellen    */
  118. CreateTimer(unit)
  119.    ULONG unit;
  120.    {
  121.  
  122.       int error;
  123.       struct MsgPort *timerport;
  124.       struct timerequest *timermsg;
  125.  
  126.       timerport = CreatePort(0,0);
  127.       if(timerport == NULL) return(NULL);
  128.  
  129.       timermsg = (struct timerequest *)
  130.             CreateExtIO(timerport,sizeof(struct timerequest));
  131.       if(timermsg == NULL) return(NULL);
  132.  
  133.       error = OpenDevice(TIMERNAME,unit,timermsg,0);
  134.       if(error != 0) {
  135.          DeleteTimer(timermsg);
  136.          return(NULL);
  137.       }
  138.       return(timermsg);
  139.  
  140.    }
  141.  
  142. int                                 /* Diese Funktion ist fⁿr das Timing */
  143. MicroDelay(MicroSeconds)            /* mit dem Chip verantwortlich, sie  */
  144.    int MicroSeconds;                /* wartet ca. 300ms, dann wird der   */
  145.    {                                /* nΣchste Befehl abgearbeitet       */
  146.  
  147.       struct timeval currentval;
  148.       struct timerequest *tr;
  149.  
  150.       currentval.tv_secs = 0;
  151.       currentval.tv_micro = MicroSeconds;
  152.  
  153.       if((tr = CreateTimer(UNIT_MICROHZ)) == NULL)
  154.          return(-1);
  155.       tr->tr_node.io_Command = TR_ADDREQUEST;
  156.       tr->tr_time = currentval;
  157.  
  158.       DoIO(tr);
  159.       DeleteTimer(tr);
  160.       return(0);
  161.    }
  162.  
  163. void        /* Diese Funktion gibt einen Takt aus */
  164. outdata()
  165.    {
  166.  
  167.       CLOCKHIGH;
  168.       MicroDelay(300);
  169.       CLOCKLOW;
  170.       MicroDelay(300);
  171.    }
  172.  
  173. void
  174. WriteTicTac()       /* Stellen von TicTac */
  175.    {
  176.  
  177.       register int i,j;
  178.       char TicTacTime[8];
  179.  
  180.       TicTacTime[1] = IntToBCD(ToBeWritten.TDhours);
  181.       TicTacTime[2] = IntToBCD(ToBeWritten.TDminutes);
  182.       TicTacTime[3] = IntToBCD(ToBeWritten.TDdate);
  183.       TicTacTime[4] = IntToBCD(ToBeWritten.TDmonth);
  184.       TicTacTime[5] = IntToBCD(ToBeWritten.TDyear);
  185.       TicTacTime[6] = IntToBCD(ToBeWritten.TDday_of_week);
  186.       TicTacTime[7] = IntToBCD(ToBeWritten.TDseconds);
  187.  
  188.       SELECT;
  189.       MicroDelay(300);
  190.       DataHigh();
  191.  
  192.       for(i=1;i<4;i++)
  193.          outdata();
  194.  
  195.       DataLow();
  196.       outdata();
  197.  
  198.       for(i=1;i<8;i++)
  199.          for(j=0;j<8;j++) {
  200.             if(TicTacTime[i] & ('\001' << 7-j))
  201.                DataHigh();
  202.             else
  203.                DataLow();
  204.             outdata();
  205.          }
  206.  
  207.       DESELECT;
  208.    }
  209.  
  210. int               /* Lesen von TicTac */
  211. ReadTicTac()
  212.    {
  213.  
  214.       register int i,j;
  215.       char TicTacTime[8];
  216.  
  217.       SELECT;
  218.       MicroDelay(300);
  219.       DataHigh();
  220.  
  221.       for (i=1;i<6;i++)
  222.          outdata();
  223.  
  224.       SETDATATOINPUT;
  225.  
  226.       for(i=1;i<8;i++) {
  227.          TicTacTime[i] = '\000';
  228.          for(j=0;j<8;j++) {
  229.             outdata();
  230.             firedata = *myprao;
  231.             firedata = firedata & OnlyBit7;
  232.             firedata = (firedata >> 7-j) & ('\001'<<j);
  233.             TicTacTime[i] = TicTacTime[i] | firedata;
  234.          }
  235.       }
  236.  
  237.       DESELECT;
  238.  
  239.       ToBeRead.TDhours     = BCDToInt(TicTacTime[1]);
  240.       ToBeRead.TDminutes   = BCDToInt(TicTacTime[2]);
  241.       ToBeRead.TDdate      = BCDToInt(TicTacTime[3]);
  242.       ToBeRead.TDmonth     = BCDToInt(TicTacTime[4]);
  243.       ToBeRead.TDyear      = BCDToInt(TicTacTime[5]);
  244.       ToBeRead.TDday_of_week=BCDToInt(TicTacTime[6]);
  245.       ToBeRead.TDseconds   = BCDToInt(TicTacTime[7]);
  246.  
  247.       if(ToBeRead.TDhours == 165 && ToBeRead.TDyear == 165)
  248.          return(-1);
  249.  
  250.       return(0);
  251.  
  252.    }
  253.  
  254. void                    /* Diese Prozedur wandelt das Systemdatum der */
  255. CalcDate(seconds)       /* Amiga in ein "normales" Datum              */
  256.    LONG seconds;
  257.    {
  258.  
  259.       int y,year,i;
  260.  
  261.       year=78;
  262.       y=1;
  263.  
  264.       while(y==1)
  265.          if (year % 4 == 0 )            /* Schaltjahr */
  266.             if (seconds >= 31622400L) {
  267.               ++year;
  268.               seconds -= 31622400L;
  269.             }
  270.             else
  271.               y = 86400;
  272.          else                           /* kein Schaltjahr */
  273.             if(seconds >= 31536000L) {
  274.                 ++year;
  275.                 seconds -= 31536000L;
  276.             }
  277.             else
  278.               y = 0;
  279.  
  280.       ToBeWritten.TDyear = year;
  281.  
  282.       i = 12;
  283.       do {
  284.            if( i <= 2) y = 0;
  285.  
  286.            if(seconds >= monthseconds[i]+y)
  287.              year = -1;
  288.            else
  289.              --i;
  290.          }while(year != -1);
  291.  
  292.       ToBeWritten.TDmonth = i;
  293.  
  294.       seconds -= (monthseconds[i]+y);
  295.  
  296.       ToBeWritten.TDdate = seconds / 86400L + 1;
  297.       seconds -= ((ToBeWritten.TDdate-1)*86400L);
  298.  
  299.       ToBeWritten.TDhours = seconds / 3600;
  300.       seconds -= ToBeWritten.TDhours * 3600;
  301.  
  302.       ToBeWritten.TDminutes = seconds / 60;
  303.       seconds -= ToBeWritten.TDminutes * 60;
  304.  
  305.       ToBeWritten.TDseconds = seconds;
  306.  
  307.       ToBeWritten.TDday_of_week = 0;         /* Wochentag wird ignoriert */
  308.  
  309.    }
  310.  
  311. LONG
  312. CalcSeconds(month,year)       /* Umwandlung des Jahres und Monats in  */
  313.    int month,year;            /* Sekunden seit dem 01.01.78           */
  314.    {
  315.  
  316.       register int y;
  317.       LONG seconds = 0L;
  318.  
  319.       for(y=78;y<year;y++)
  320.          if(y%4 == 0 )                 /* Schaltjahr */
  321.             seconds += 31622400L;
  322.          else
  323.             seconds += 31536000L;
  324.  
  325.       if ((y%4 == 0) && (month > 2))
  326.             seconds += 86400L;
  327.  
  328.       seconds += monthseconds[month];
  329.  
  330.       return(seconds);
  331.    }
  332.  
  333. int                  /* SetNewTime() stellt die Uhr der Amiga neu */
  334. SetNewTime(secs)
  335.    LONG secs;
  336.    {
  337.  
  338.       struct timerequest *tr;
  339.  
  340.       if((tr = CreateTimer(UNIT_MICROHZ)) == NULL) return(-1);
  341.  
  342.       tr->tr_node.io_Command = TR_SETSYSTIME;
  343.       tr->tr_time.tv_secs = secs;
  344.       tr->tr_time.tv_micro = 0;
  345.  
  346.       DoIO(tr);
  347.       DeleteTimer(tr);
  348.       return(0);
  349.    }
  350.  
  351. int
  352. GetSystemTime(tv)       /* GetSystemTime() liest die Uhr der Amiga */
  353.    struct timeval *tv;
  354.    {
  355.  
  356.       struct timerequest *tr;
  357.       if((tr = CreateTimer(UNIT_MICROHZ)) == NULL )return(-1);
  358.  
  359.       tr->tr_node.io_Command = TR_GETSYSTIME;
  360.       DoIO(tr);
  361.  
  362.       *tv = tr->tr_time;
  363.  
  364.       DeleteTimer(tr);
  365.       return(0);
  366.  
  367.    }
  368.  
  369. char           /* Wird von Ausgabe() zur Konvertierung des TimeAndDate- */
  370. Zehnerrest(a)  /* struct in eine Zeichenkette verwendet */
  371.    int a;
  372.  
  373.    {
  374.       return(a % 10 + '0');
  375.    }
  376.  
  377. void           /* Ausgabe() gibt das Datum und die Zeit im deutschen    */
  378. Ausgabe()      /* Format (mit fⁿhrenden Nullen) aus.                    */
  379.    {
  380.  
  381.       char Zeile[] = "\n\2331;33mE050-C16\2330m:   .  .    ,   :  .   Uhr\n";
  382.       int z;
  383.  
  384.       z = ToBeRead.TDdate;
  385.       Zeile[21] = Zehnerrest(z);
  386.       Zeile[20] = Zehnerrest(z/=10);
  387.  
  388.       z = ToBeRead.TDmonth;
  389.       Zeile[24] = Zehnerrest(z);
  390.       Zeile[23] = Zehnerrest(z/=10);
  391.  
  392.       z = ToBeRead.TDyear+1900;
  393.       Zeile[29] = Zehnerrest(z);
  394.       Zeile[28] = Zehnerrest(z/=10);
  395.       Zeile[27] = Zehnerrest(z/=10);
  396.       Zeile[26] = Zehnerrest(z/=10);
  397.  
  398.       z = ToBeRead.TDhours;
  399.       Zeile[33] = Zehnerrest(z);
  400.       Zeile[32] = Zehnerrest(z/=10);
  401.  
  402.       z = ToBeRead.TDminutes;
  403.       Zeile[36] = Zehnerrest(z);
  404.       Zeile[35] = Zehnerrest(z/=10);
  405.  
  406.       z = ToBeRead.TDseconds;
  407.       Zeile[39] = Zehnerrest(z);
  408.       Zeile[38] = Zehnerrest(z/=10);
  409.  
  410.       /* Auf printf() wird verzichtet, da es unn÷tig Speicher fri▀t.   */
  411.       /* Statt dessen wird die normale DOS-Funktion Write() verwendet. */
  412.       /* Auch die restlichen Ausgaben erfolgen mit Write()!.           */
  413.  
  414.       Write(Output(),Zeile,45);
  415.  
  416.    }
  417.  
  418.  
  419. void
  420. main(argc,argv)
  421.    int argc;
  422.    char *argv[];
  423.    {
  424.  
  425.    struct timeval currentval;
  426.    LONG SysSeconds;
  427.    int ticErr=0;
  428.  
  429.    myddrao = (char *)0xbfe2ffL;
  430.    myprao =  (char *)0xbfe0ffL;
  431.  
  432.    if(!(DOSBase = (struct DosLibrary *)
  433.             OpenLibrary("dos.library",0L))) exit(30);
  434.  
  435.    if((PotgoBase = (APTR *)OpenResource("potgo.resource")) == NULL)
  436.       {
  437.          Write(Output(),"\2331;33mE050-C16\2330m: OpenResource 'potgo.resource' failed.\n",57);
  438.          ticErr = 26;
  439.          goto ErrExit;
  440.       }
  441.  
  442.    bits = DATRX | DATRY | OUTRX | OUTRY;
  443.  
  444.    allocated = AllocPotBits(bits);
  445.  
  446.    if(allocated != bits) {
  447.       Write(Output(),"\2331;33mE050-C16\2330m: AllocPotBits() failed.\n",42);
  448.       ticErr = 21;
  449.       goto ErrExit;
  450.       }
  451.  
  452.    DESELECT;
  453.    CLOCKLOW;
  454.  
  455.    if(argc == 1)
  456.     {
  457.       if(ReadTicTac() == -1) {
  458.         Write(Output(),"\2331;33mE050-C16:\2330m\n",19);
  459.         Write(Output(),"TicTac kann Zeit nicht lesen.\n",30);
  460.         ticErr = 11;
  461.         goto ErrExit;
  462.       }
  463.  
  464.       Ausgabe();
  465.  
  466.     }
  467.    else if (*argv[1] == 'l' || *argv[1] == 'L') {
  468.       if(ReadTicTac() == -1) {
  469.         Write(Output(),"\2331;33mE050-C16:\2330m\n",19);
  470.         Write(Output(),"TicTac kann Zeit nicht lesen.\n",30);
  471.         Write(Output(),"Systemzeit nicht aktualisiert!\n",31);
  472.         ticErr = 12;
  473.         goto ErrExit;
  474.       }
  475.  
  476.       SysSeconds =   CalcSeconds(ToBeRead.TDmonth,ToBeRead.TDyear) +
  477.                      (LONG)ToBeRead.TDseconds +
  478.                      (LONG)ToBeRead.TDminutes * 60L +
  479.                      (LONG)ToBeRead.TDhours * 3600L +
  480.                      (LONG)(ToBeRead.TDdate-1)*86400L;
  481.  
  482.       if(SetNewTime(SysSeconds) == -1) {
  483.         Write(Output(),"\2331;33mE050-C16\2330m: SetSystemTime failed.\n",41);
  484.         ticErr = 13;
  485.         goto ErrExit;
  486.       }
  487.  
  488.       Ausgabe();
  489.  
  490.       }
  491.    else if (*argv[1] == 's' || *argv[1] == 'S') {
  492.       if(GetSystemTime(¤tval) == -1) {
  493.         Write(Output(),"\2331;33mE050-C16\2330m: GetSysTime() failed.\n",40);
  494.         ticErr = 10;
  495.         goto ErrExit;
  496.       }
  497.  
  498.       CalcDate(currentval.tv_secs);
  499.       WriteTicTac();
  500.       Write(Output(),"TicTac gestellt!\n",17);
  501.  
  502.       }
  503.    else
  504.       Write(Output(),"AUFRUF: TicTac [load][save]\n",28);
  505.  
  506.  
  507. ErrExit:
  508.    if(ticErr < 30)
  509.         SETDATATOINPUT;
  510.    if(ticErr < 25)
  511.         FreePotBits(allocated);
  512.  
  513.    CloseLibrary(DOSBase);
  514.  
  515.    /****************************************************************/
  516.    /* Fehlercodes:                                                 */
  517.    /* ------------                                                 */
  518.    /*  0:   TicTac ordentlich beendet,                             */
  519.    /* 10:   Systemzeit konnte nicht gelesen werden,                */
  520.    /* 11:   Chip konnte nicht gelen werden (Uhr angeschlossen ?),  */
  521.    /* 12:   dto. beim Versuch Systemzeit nach Chip zu stellen,     */
  522.    /* 13:   Systemzeit konnte nicht verΣndert werden,              */
  523.    /* 21:   AllocPortBits() lieferte Fehler,                       */
  524.    /* 26:   'potgo.resource' konnte nicht ge÷ffnet werden,         */
  525.    /* 30:   DOS konnte nicht ge÷ffnet werden (?!).                 */
  526.    /****************************************************************/
  527.  
  528.    exit(ticErr);
  529.    }
  530.  
  531.